package Q16_14_Best_Line; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; import CtCILibrary.HashMapList; public class Question { /* Find line that goes through most number of points. */ public static Line findBestLine(GraphPoint[] points) { HashMapList<Double, Line> linesBySlope = getListOfLines(points); return getBestLine(linesBySlope); } /* Add each pair of points as a line to the list. */ public static HashMapList<Double, Line> getListOfLines(GraphPoint[] points) { HashMapList<Double, Line> linesBySlope = new HashMapList<Double, Line>(); for (int i = 0; i < points.length; i++) { for (int j = i + 1; j < points.length; j++) { Line line = new Line(points[i], points[j]); double key = Line.floorToNearestEpsilon(line.slope); linesBySlope.put(key, line); } } return linesBySlope; } /* Return the line with the most equivalent other lines. */ public static Line getBestLine(HashMapList<Double, Line> linesBySlope) { Line bestLine = null; int bestCount = 0; Set<Double> slopes = linesBySlope.keySet(); for (double slope : slopes) { ArrayList<Line> lines = linesBySlope.get(slope); for (Line line : lines) { /* count lines that are equivalent to current line */ int count = countEquivalentLines(linesBySlope, line); /* if better than current line, replace it */ if (count > bestCount) { bestLine = line; bestCount = count; bestLine.Print(); System.out.println(bestCount); } } } return bestLine; } /* Check hashmap for lines that are equivalent. Note that we need to check one epsilon above and below the actual slope * since we're defining two lines as equivalent if they're within an epsilon of each other. */ public static int countEquivalentLines(HashMapList<Double, Line> linesBySlope, Line line) { double key = Line.floorToNearestEpsilon(line.slope); int count = countEquivalentLines(linesBySlope.get(key), line); count += countEquivalentLines(linesBySlope.get(key - Line.epsilon), line); count += countEquivalentLines(linesBySlope.get(key + Line.epsilon), line); return count; } /* Count lines within an array of lines which are "equivalent" (slope and y-intercept are within an epsilon value) to a given line */ public static int countEquivalentLines(ArrayList<Line> lines, Line line) { if (lines == null) { return 0; } int count = 0; for (Line parallelLine : lines) { if (parallelLine.isEquivalent(line)) { count++; } } return count; } public static GraphPoint[] createPoints() { int n_points = 100; System.out.println("Points on Graph\n***************"); GraphPoint[] points = new GraphPoint[n_points - 1]; for (int i = 0; i < n_points / 2; i++) { GraphPoint p = new GraphPoint(i, 2.3 * ((double)i) + 20.0); points[i] = p; System.out.println(p.toString()); } for (int i = 0; i < n_points / 2 - 1; i++) { GraphPoint p = new GraphPoint(i, 3.0 * ((double)i) + 1.0); points[n_points / 2 + i] = p; System.out.println(p.toString()); } System.out.println("****************\n"); return points; } public static int validate(Line line, GraphPoint[] points) { int count = 0; for (int i = 0; i < points.length; i++) { for (int j = i + 1; j < points.length; j++) { Line other = new Line(points[i], points[j]); if (line.isEquivalent(other)) { count++; } } } return count; } public static void main(String[] args) { GraphPoint[] points = createPoints(); Line line = findBestLine(points); line.Print(); System.out.println(validate(line, points)); } }